package cn.zjh.user.service.service.impl;

import cn.zjh.base.constants.BaseConstants;
import cn.zjh.base.exception.BusinessException;
import cn.zjh.user.service.service.IVerifyCodeService;
import cn.zjh.base.utils.StrUtils;
import cn.zjh.base.utils.VerifyCodeUtils;
import cn.zjh.base.vo.RegisterVo;
import cn.zjh.user.domain.User;
import cn.zjh.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {


    @Autowired
    private RedisTemplate redisTemplate;


    @Autowired
    private UserMapper userMapper;

    /**
    * @Title: graph
    * @Description: 生成base64图形验证码字符串
    * @Author: Mr.Zhang
    * @Version: 1.0
    * @Date:  2022/7/6 16:30
    * @Parameters:
    * @Return
    */
    @Override
    public String graph(String imageCodeKey) {
        //判断key是否为空
        if (StringUtils.isEmpty(imageCodeKey)){
            throw  new BusinessException("参数不能为空！");
        }
        //生成随机串
        String code = StrUtils.getComplexRandomString(4);

        //将前端UUID生成的key和后端生成的随机串value设置到redis中，过期时间5分钟
        redisTemplate.opsForValue().set(imageCodeKey,code,5, TimeUnit.MINUTES);

        //将code生成图形并编码为base64
        String base64Code = VerifyCodeUtils.VerifyCode(100, 38, code);

        return base64Code;
    }


    /**
    * @Title: smsCode
    * @Description: 发送手机验证码
    * @Author: Mr.Zhang
    * @Version: 1.0
    * @Date:  2022/7/6 16:29
    * @Parameters:
    * @Return
    */
    @Override
    public void smsCode(RegisterVo vo) {
        String phone = vo.getPhone();
        String type = vo.getType();
        //非空校验
        if (StringUtils.isEmpty(phone) || StringUtils.isEmpty(type)){
            throw new BusinessException("参数不能为空，请输入必要参数！");
        }
        if ("register".equals(type)){//如果是注册
            //判断图形验证码
            isImageCode(vo);
            //判断用户是否注册
            User user = userMapper.loadByPhone(phone);
            if (user != null){
                throw new BusinessException("用户已注册，请直接登录!");
            }
            //发送短信
            sendSmsCode(BaseConstants.VerifyCodeConstant.BUSINESS_REGISTER_PREFIX,phone);
        }else if ("binder".equals(type)){//如果是登录绑定
            //发送短信
            sendSmsCode(BaseConstants.VerifyCodeConstant.BUSINESS_BINDER_PREFIX,phone);
        }
    }


    /**
    * @Title: sendSmsCode
    * @Description: 短信发送
    * @Author: Mr.Zhang
    * @Version: 1.0
    * @Date:  2022/7/10 21:48
    * @Parameters:
    * @Return
    */
    public void sendSmsCode(String businessKey,String phone){
        //根据电话号码拼接业务键，去redis中获取对应的value值，判断是否存在
        String phoneCodeKey = businessKey+phone;
        //获取验证码
        Object smsCodeValueTmp = redisTemplate.opsForValue().get(phoneCodeKey);

        //储存验证码
        String smsCode = "";
        //判断验证码的是否为空，如果为空说明验证码过期或者第一次获取验证码
        if (smsCodeValueTmp == null){
            //生成验证码
            smsCode = StrUtils.getComplexRandomString(4);
        }else {
            //如果不为空，我们要判断是否事件超过一分钟，防止恶意请求验证码
            //截取老验证码的时间戳
            String[] smsCodeValueArray = smsCodeValueTmp.toString().split(":");
            //将数组中的时间戳取出，并转换为Long类型
            Long oldTimeTmp = Long.valueOf(smsCodeValueArray[0]);
            //获取当前时间戳
            long newTimeTmp = System.currentTimeMillis();
            //如果老验证码时间未过期，提示用户验证码未过期
            if(oldTimeTmp - newTimeTmp <= 1*60*1000 ){
                throw new BusinessException("验证码已发出，请稍后再试！");
            }
            //如果时间已过期，就将新的验证码存入redis
            smsCode = smsCodeValueArray[1];
        }
        //将验证码重新存入redis中，并设置过期时间三分钟
        String smsCodeValue = System.currentTimeMillis()+":"+smsCode;
        redisTemplate.opsForValue().set(phoneCodeKey,smsCodeValue,3,TimeUnit.MINUTES);
        //SmsUtils.sendCode(phone, "亲，您的验证码是："+smsCode+"，请在三分钟内使用！");
        //发送验证码
        System.out.println("亲，您的验证码是:"+smsCode);
    }


    /**
    * @Title: isImageCode
    * @Description: 图形验证码校验
    * @Author: Mr.Zhang
    * @Version: 1.0
    * @Date:  2022/7/10 21:48
    * @Parameters:
    * @Return
    */
    public void isImageCode(RegisterVo vo){
        //获取电话号码，图形验证码，图形验证码在redis中的key
        String phone = vo.getPhone();
        String imageCodeValue = vo.getImageCodeValue();
        String imageCodeKey = vo.getImageCodeKey();

        //空校验
        if (StringUtils.isEmpty(imageCodeKey)
                ||StringUtils.isEmpty(imageCodeValue)){
            throw new BusinessException("参数不能为空，请输入必要参数！");
        }

        //判断图形验证码的值是否有值且是否正确
        Object imageCodeTmp = redisTemplate.opsForValue().get(imageCodeKey);
        //验证码空判断
        if (imageCodeTmp == null){
            throw new BusinessException("图形验证码不能为空，请输入图形验证码！");
        }

        //判断图形验证码值是否正确
        if (!imageCodeTmp.toString().equalsIgnoreCase(imageCodeValue)){
            throw new BusinessException("图形验证码不正确，请重新填写！");
        }

    }

}
